package com.epoch.zuul.login;

import bean.response.ResponseBean;
import bean.response.ResultEnum;
import com.epoch.zuul.auth.dao.ConsumerDao;
import com.epoch.zuul.auth.dao.CsRoleDao;
import com.epoch.zuul.auth.dao.RolesDao;
import com.epoch.zuul.auth.role.Consumer;
import com.epoch.zuul.auth.role.Roles;
import com.epoch.zuul.auth.token.JwtToken;
import com.epoch.zuul.auth.token.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import utils.Base;
import utils.ResultInfoUtil;
import utils.validcode.DataValid;
import utils.validcode.VerifyCodeUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;

/**
 * @author admin
 */
@Service
@Slf4j
public class LoginServiceImpl implements LoginService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ConsumerDao consumerDao;

    @Autowired
    private CsRoleDao csRoleDao;

    @Autowired
    private RolesDao rolesDao;

    @Override
    public ResponseBean login(Consumer currentConsumer, String validateCode, HttpServletRequest request) {
        return loginProcess(currentConsumer,request,1);
    }

    @Override
    public ResponseBean managerLogin(Consumer currentConsumer, HttpServletRequest request) {
        return loginProcess(currentConsumer, request, 2);
    }

    /**
     * 用户注册
     * @param regConsumer
     * @param request
     * @param registerFor
     * @param validateCode
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean register(Consumer regConsumer, HttpServletRequest request,  String registerFor, String validateCode) {
        //先对验证码进行验证
        try{
            String loginValidateCode = request.getSession().getAttribute("verCode").toString();
            if (loginValidateCode == null){
                ResultInfoUtil.buildError(ResultEnum.BAD_REQUEST,"验证码已过期");
            }else if (!loginValidateCode.equals(validateCode)){
                ResultInfoUtil.buildError(ResultEnum.BAD_REQUEST,"验证码错误");
            }
        }catch (Exception e){
            ResultInfoUtil.buildError(ResultEnum.BAD_REQUEST,"验证码已过期或不存在");
        }
        if (regConsumer.getCsEmail() != null && !regConsumer.getCsEmail().equals("") && !DataValid.emailValid(regConsumer.getCsEmail())){
            logger.info("用户注册失败【邮箱{}无效】",regConsumer.getCsEmail());
            return ResultInfoUtil.buildError(ResultEnum.BAD_REQUEST,"注册失败，邮箱无效");
        }
        //对密码进行加密后注册
        String csEncodePwd = Base.encode(regConsumer.getCsPwd());
        //设置编号
        regConsumer.setCsId("U"+regConsumer.getCsPhone());
        //设置密码
        regConsumer.setCsPwd(csEncodePwd);
        consumerDao.simpleRegister(regConsumer);
        //给用户赋予身份 学生、老师
        if (!registerFor.equals("学生") && !registerFor.equals("教师")){
            registerFor = "学生";
        }
        Roles role = rolesDao.getRoleByRoleName(registerFor);
        if (role != null){
            csRoleDao.grantToCs(consumerDao.getByCsPhone(regConsumer.getCsPhone()).getId(), role.getRoleId());
        }else {
            csRoleDao.grantToCs(consumerDao.getByCsPhone(regConsumer.getCsPhone()).getId(), rolesDao.getRoleByRoleName("学生").getRoleId());
        }
        logger.info("用户注册成功 insert into 账号：{}，密码：{}",regConsumer.getCsPhone(),regConsumer.getCsPwd());
        return ResultInfoUtil.buildSuccess(ResultEnum.OK, "用户注册成功", consumerDao.getByCsPhone(regConsumer.getCsPhone()));
    }

    /**
     * 获取 图片验证码 LoginServiceImpl
     * @param request
     * @param response
     * @throws IOException
     */
    @Override
    public void loginValidateCodeB(HttpServletRequest request, HttpServletResponse response) throws IOException {

        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/jpeg");
        // 生成随机大写字串
        String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
        // 存入会话session
        HttpSession session = request.getSession(true);
        // 删除以前的
        session.removeAttribute("verCode");
        session.removeAttribute("codeTime");
        session.setAttribute("verCode", verifyCode.toLowerCase());
        System.out.println("verCode : "+verifyCode.toLowerCase());
        session.setAttribute("codeTime", new Date());
        // 生成图片
        int w = 100, h = 30;
        OutputStream out = response.getOutputStream();
        VerifyCodeUtils.outputImage(w, h, out, verifyCode);
    }

    public ResponseBean loginProcess(Consumer currentConsumer, HttpServletRequest request, Integer is_login){
        Integer after_login = 0;
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
        //封装用户的登录信息
        String jwt = JwtUtil.createJWT(currentConsumer.getCsPhone(),"back", "currentConsumer",2*2400*60*600);
        JwtToken jwtToken = new JwtToken(jwt,currentConsumer.getCsPwd());
        try{
            subject.login(jwtToken);
            Consumer consumer = consumerDao.getByCsPhone(currentConsumer.getCsPhone());
            logger.info("用户登录成功：账号{},用户名称：{}  ,密码{}",currentConsumer.getCsPhone(),currentConsumer.getCsName(),currentConsumer.getCsPwd());
            HashMap<String,Object> result = new HashMap<>();
            result.put("consumer", consumer);
            result.put("jwtToken",jwtToken);
            result.put("is_login", is_login);
            if (is_login == 2){
                //管理员登录
                after_login = 2;
            }
            result.put("after_login",after_login);
            return ResultInfoUtil.buildSuccess(ResultEnum.OK,"用户登录成功",result);
        }catch (UnknownAccountException e){
            logger.info("用户登录失败：账号{},用户名称：{}  ,密码{}",currentConsumer.getCsPhone(),"  ",currentConsumer.getCsPwd());
            is_login = 0;
            return new ResponseBean(401, "用户登录失败，用户不存在",is_login);
        }catch (IncorrectCredentialsException e){
            Consumer consumer = consumerDao.getByCsPhone(currentConsumer.getCsPhone());
            logger.info("用户登录失败：账号{},用户名称：{}  ,密码{}",currentConsumer.getCsPhone(),consumer.getCsName(),consumer.getCsPwd());
            is_login = 0;
            return new ResponseBean(401, "用户登录失败，密码错误",is_login);
        }
    }

}
